from closure_linter import javascripttokenizer
from closure_linter.javascripttokens import JavaScriptTokenType
from closure_linter import tokenutil

def _GetTokenIterator(first_token):
  token = first_token

  while token is not None:
    yield token
    token = token.next

def _GetDocFlagCommentToken(doc_flag_node):
  assert doc_flag_node.type is JavaScriptTokenType.DOC_FLAG

  comment_node = doc_flag_node.next

  if comment_node.type is not JavaScriptTokenType.COMMENT:
    # TODO(nnaze): Make exception class that auto-prints token in error message.
    raise ParseError('JsDoc flag should be followed by a comment specifying namespace', token)  

  return comment_node.string.strip()

def GetJsDocDependencies(source):

  provides = set()
  requires = set()

  lines = source.splitlines()
  tokenizer = javascripttokenizer.JavaScriptTokenizer()
  first_token = tokenizer.TokenizeFile(lines)

  for token in _GetTokenIterator(first_token):

    if token.type is JavaScriptTokenType.DOC_FLAG:

      # @requires tag
      if token.string == '@requires':
        requires.add(_GetDocFlagCommentToken(token))

      # @namespace tag
      if token.string == '@namespace':
        provides.add(_GetDocFlagCommentToken(token))

      # @class tag
      if token.string == '@class':
        provides.add(_GetDocFlagCommentToken(token))

  return provides, requires

class ParseError(Exception):
  
  def __init__(self, msg, token):
    super(ParseError, self).__init__(msg)

  def __str__(self):
    return '%s %s' % (msg, str(token))

